package pkg

import (
	"gin-wheel/global"
	"time"

	"github.com/gomodule/redigo/redis"
)

// 初始化进程池方法
func RedisPool() *redis.Pool {
	redisPool := &redis.Pool{
		MaxIdle:     global.RedisSetting.MaxIdle,                                  //最大空闲数
		MaxActive:   global.RedisSetting.MaxActive,                                //最大活跃数
		IdleTimeout: time.Duration(global.RedisSetting.IdleTimeout) * time.Second, //最大的空闲连接等待时间，超过此时间后，空闲连接将被关闭
		Dial: func() (redis.Conn, error) {
			//此处对应redis ip及端口号
			conn, err := redis.Dial("tcp", global.RedisSetting.Path)
			if err != nil {
				return nil, err
			}
			auth := global.RedisSetting.Auth //通过配置项设置redis密码
			if len(auth) >= 1 {
				if _, err := conn.Do("AUTH", auth); err != nil {
					_ = conn.Close()
					return nil, err
				}
			}
			_, _ = conn.Do("select", global.RedisSetting.IndexDb)
			return conn, err
		},
	}
	return redisPool
}

//  从连接池获取一个redis连接
func GetOneRedisClient() *RedisClient {
	maxRetryTimes := global.RedisSetting.ConnFailRetryTimes
	var oneConn redis.Conn
	for i := 1; i <= maxRetryTimes; i++ {
		oneConn = global.RedisPool.Get()
		if oneConn.Err() != nil {
			//variable.ZapLog.Error("Redis：网络中断,开始重连进行中..." , zap.Error(oneConn.Err()))
			if i == maxRetryTimes {
				global.ZapLog.Error("获取redis客户端失败")
				return nil
			}
			//如果出现网络短暂的抖动，短暂休眠后，支持自动重连
			time.Sleep(time.Second * time.Duration(global.RedisSetting.ReConnectInterval))
		} else {
			break
		}
	}
	return &RedisClient{oneConn}
}

// 定义一个redis客户端结构体
type RedisClient struct {
	client redis.Conn
}

// 为redis-go 客户端封装统一操作函数入口
func (r *RedisClient) Execute(cmd string, args ...interface{}) (interface{}, error) {
	return r.client.Do(cmd, args...)
}

// 释放连接到连接池
func (r *RedisClient) ReleaseOneRedisClient() {
	_ = r.client.Close()
}

//  封装几个数据类型转换的函数

//bool 类型转换
func (r *RedisClient) Bool(reply interface{}, err error) (bool, error) {
	return redis.Bool(reply, err)
}

//string 类型转换
func (r *RedisClient) String(reply interface{}, err error) (string, error) {
	return redis.String(reply, err)
}

//strings 类型转换
func (r *RedisClient) Strings(reply interface{}, err error) ([]string, error) {
	return redis.Strings(reply, err)
}

//Float64 类型转换
func (r *RedisClient) Float64(reply interface{}, err error) (float64, error) {
	return redis.Float64(reply, err)
}

//int 类型转换
func (r *RedisClient) Int(reply interface{}, err error) (int, error) {
	return redis.Int(reply, err)
}

//int64 类型转换
func (r *RedisClient) Int64(reply interface{}, err error) (int64, error) {
	return redis.Int64(reply, err)
}

//uint64 类型转换
func (r *RedisClient) Uint64(reply interface{}, err error) (uint64, error) {
	return redis.Uint64(reply, err)
}

//Bytes 类型转换
func (r *RedisClient) Bytes(reply interface{}, err error) ([]byte, error) {
	return redis.Bytes(reply, err)
}
